from django.shortcuts import render
from django.core import serializers
from django.http import JsonResponse
from django.views import View
from django.utils.decorators import method_decorator
import json
from django.core.paginator import *
from .models import StuModel
from utils.allow_origin import allow_origin

from django.middleware.csrf import get_token
def get_csrftoken(request):
	'''前端访问这个视图,这个视图返回的Response响应头中会包含Set-Cookie:csrftoken=xxxxx'''
	csrf = get_token(request)
	res = JsonResponse({'X-CSRFToken':csrf})
	return res

# CBV(基于类的视图)和FBV(基于函数的视图)

class StudentView(View):
	error = ''
	@method_decorator(allow_origin)
	def get(self, request):
		"""
		学生数据查询接口
		功能:分页返回学生数据,前端传递page=1,就返回第一页的数据;

		:param request:
		:param page: 页码
		:param size: 每页的数据个数
		:return:
		"""
 		# 1.查询所有的学生数据
		stus = StuModel.objects.all().order_by('id')
		# 2.根据前端ajax传递的page&size参数开始做分页器
		size = request.GET.get('size', '2')
		page_number = int(request.GET.get('page', '1'))
		# paginator = Paginator(stus, size)
		paginator = QuerySetPaginator(stus, size)
		try:
			page = paginator.page(page_number)
		except (EmptyPage,PageNotAnInteger,InvalidPage):
			self.error = '已经是最后一页了'
			page = paginator.page(paginator.num_pages)
			page_number = paginator.num_pages

		# 3.开始做分页
		# 假设分页器上只显示5个页码,分页器出现滚动之后,当前页始终在中间,当前页前后各两个页码;
		if paginator.num_pages <= 5:
			# 全部展示,将当前所有页码的值返回给前端
			page_nums = [x for x in range(1, paginator.num_pages+1)]
		elif int(page_number) < 4:
			# 如果总页数超过5页了,但是当前页的页码小于4的时候,分页器是同样不会滚动的.
			# 12345
			page_nums = [x for x in range(1, 6)]
		elif int(page_number) - 4 >= 0 and page_number<= paginator.num_pages -2:
			# 如果总页数超过5页,分页器需要滚动
			page_nums = [x for x in range(page_number-2, page_number+3)]
		else:
			# 超过5页,但是已经到最后一页了
			page_nums = [x for x in range(paginator.num_pages-4, paginator.num_pages+1)]

		# 4.向前端返回json数据
		data = {
			'code': 100,
			'status': 'ok',
			'error': self.error,
			'total_pages': len(stus),	# 总的数据个数
			'has_previous': page.has_previous(),
			'previous_url': page_number-1 if page.has_previous() else None,
			'has_next': page.has_next(),
			'next_url': page_number+1 if page.has_next() else None,
			'page_nums': page_nums,
			'current_page':page.number,
			# 当前页的数据列表
			'results': json.loads(serializers.serialize('json',page.object_list,use_natural_primary_keys=True)),
		}
		# response = JsonResponse(data,status=200)
		# 允许所有的源,向这个接口发生请求并得到相应,(改变浏览器默认的禁止跨域,此时就是允许跨域.)
		# response['Access-Control-Allow-Origin'] = '*'
		return data

	@method_decorator(allow_origin)
	def post(self, request):
		'''
		添加学员功能
		:param request:
		:return:
		'''
		sid = request.POST.get('sid')
		name = request.POST.get('name')
		age = request.POST.get('age')
		data = {}
		try:
			stu = StuModel(id=int(id),name=name,age=age)
			stu.save()
		except Exception as e:
			data['status'] = 'error'
			data['message'] = '添加失败'
		else:
			data['status'] = 'ok'
			data['message'] = '添加成功'
		return data



'''
前后端分离中CSRF的问题
1.在前后端分离中,接口的调用本身就是一种跨站请求,因为这个接口既要被安卓端的站点访问,又要被苹果端的站点访问,所以在这种模式下,csrf的认证就失去作用了.解决方案,取消CsrfMiddleware中间件对于CSRF的认证;
2.如果在前后端分离中,必须要进行csrf认证,也可以实现;

CSRF工作原理:
FROM表单提交POST请求时:
每次渲染页面,在Html模板中,{{ csrf_token }}都会加载一个随机字符串,每次的值都是不一样的;

Ajax提交POST请求时:
不一定非得通过{{ csrf_token }} 来认证csrf,也可以通过在请求头中,添加X-CSRFToken:csrftoken字段,同样也能通过csrf认证;
由于前后端分离:前端页面无法识别{{ csrf_token }} 需要在请求投中添加 X-CSRFtoken



'''
from django.views.decorators.csrf import csrf_exempt,csrf_protect

class StudentInspectView(View):
	"""
	检查学员学号是否唯一的CBV视图类.
	"""
	@method_decorator(allow_origin)
	def post(self, request):
		stu_id = request.POST.get('sid')
		data = {}
		if stu_id and StuModel.objects.filter(id=stu_id):
			# 学号已经存在
			data['is_exist'] = 1
			data['message'] = '该学号已经存在'
		else:
			data['is_exist'] = 0
			data['message'] = '该学号可以使用'
		return data
